package com.yanqu.road.server.manger.activity.cat;

import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.cat.*;
import com.yanqu.road.entity.activity.cat.config.CatMissionInfo;
import com.yanqu.road.entity.activity.cat.config.CatNpcInfo;
import com.yanqu.road.entity.enums.eActivityType;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.cat.CatActivityConfig;
import com.yanqu.road.server.gameplayer.module.activity.cat.CatModule;
import com.yanqu.road.server.gameplayer.module.activity.cat.action.*;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.util.*;

public class CatMgr extends TempMgr {

    private static CatActivityConfig config;

    private static RandomHelper randomHelper = new RandomHelper();

    public CatMgr() {
    }

    @Override
    public boolean init() throws Exception {
        BaseElementAction.getActionMap().put(eElementTypes.NotNull.getType(), new NotNullElementAction(eElementTypes.NotNull.getType()));
        BaseElementAction.getActionMap().put(eElementTypes.Null.getType(), new NullElementAction(eElementTypes.Null.getType()));
        BaseElementAction.getActionMap().put(eElementTypes.Monster.getType(), new MonsterElementAction(eElementTypes.Monster.getType()));
        BaseElementAction.getActionMap().put(eElementTypes.Dharma.getType(), new DharmaElementAction(eElementTypes.Dharma.getType()));
        BaseElementAction.getActionMap().put(eElementTypes.Omnipotent.getType(), new OmnipotentElementAction(eElementTypes.Omnipotent.getType()));
        BaseElementAction.getActionMap().put(eElementTypes.Role.getType(), new RoleElementAction(eElementTypes.Role.getType()));
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    public static void reloadActivityData() {
        getLogger().info("reload cat Activity start");
        ActivityInfo tempActivityInfo;
        List<ActivityInfo> openActivityInfoList = NormalActivityMgr.getOpenActivityInfoList(eActivityType.Cat.getValue());
        if (openActivityInfoList.isEmpty()) {
            getLogger().info("no cat Activity in show time");
            config = null;
        } else {
            tempActivityInfo = openActivityInfoList.get(0);

            CatActivityConfig configTemp = new CatActivityConfig();
            configTemp.setActivityInfo(tempActivityInfo);

            boolean initSuccess = configTemp.init();

            if(!initSuccess){
                config = null;
                return;
            }

            config = configTemp;
        }
        getLogger().info("reload cat Activity finish");

        // 在线玩家下发数据
        for (GamePlayer gamePlayer : GamePlayerMgr.getAllOnlinePlayer()) {
            CatModule module = gamePlayer.getModule(CatModule.class);
            module.syncConfig();
            module.initUserData();
            module.syncUserData();
        }
    }

    public static ActivityInfo getActivityInfo() {
        if(config == null) {
            return null;
        }
        return config.getActivityInfo();
    }

    public static int getActivityId(){
        if(config == null){
            return 0;
        }
        if(config.getActivityInfo() == null){
            return 0;
        }
        return config.getActivityInfo().getActivityId();
    }

    @Override
    public boolean stop() {
        return false;
    }

    public static CatActivityConfig getConfig() {
        return config;
    }

    public static RandomHelper getRandomHelper() {
        return randomHelper;
    }

    public static void setRandomHelper(RandomHelper randomHelper) {
        CatMgr.randomHelper = randomHelper;
    }

    /**
     * 位置是否有效
     */
    public static boolean isValid(Position position) {
        return isValid(position.getX(), position.getY());
    }

    public static boolean isValid(int x, int y) {
        return x >= 0 && y >= 0 && y < CatActivityConfig.ROW_NUM && x < CatActivityConfig.COLUMN_NUM;
    }

    public static List<Integer> getRandomElementIndex() {
        int max = CatActivityConfig.ROW_NUM * CatActivityConfig.COLUMN_NUM;
        //随机位置
        return RandomHelper.getDifferentRandomNum(max, max);
    }

    /**
     * 达摩颜色
     */
    public static int getElementColor(int id){
        return id % 1000;
    }

    /**
     * 复制盘面
     */
    public static Element[][] copy(Element[][] elements){
        Element[][] copy = new Element[CatActivityConfig.ROW_NUM][CatActivityConfig.COLUMN_NUM];
        for (int i = 0; i < CatActivityConfig.ROW_NUM; i++) {
            for (int k = 0; k < CatActivityConfig.COLUMN_NUM; k++) {
                copy[i][k] = elements[i][k].clone();
            }
        }
        return copy;
    }

    /**
     * 关卡星级
     */
    public static int getPassStar(int round, CatMissionInfo missionInfo){
        List<Integer> list = StringUtils.stringToIntegerList(missionInfo.getRoundsNumber(), "\\|");
        int star = 0;
        for (int i = 1; i < list.size(); i++) {
            if(round <= list.get(i)){
                star = i;
            }
        }
        return star;
    }

    /**
     * 关卡随机奖励
     */
    public static String getMissionRandomReward(String weightRewards){
        if(StringUtils.isNullOrEmpty(weightRewards) || "0".equals(weightRewards)){
            return "";
        }
        List<String> rewardList = new ArrayList<>();
        List<Integer> weightList = new ArrayList<>();
        List<String> itemList = StringUtils.stringToStringList(weightRewards, "\\|");
        for (String item : itemList) {
            List<String> list = StringUtils.stringToStringList(item, ";");
            rewardList.add(list.get(0));
            weightList.add(Integer.parseInt(list.get(1)));
        }
        int idx = RandomHelper.getRandomIndexByWeight(weightList);
        return rewardList.get(idx);
    }

    /**
     * 特定元素统计
     */
    public static int elementCount(Element[][] elements, int type){
        int count = 0;
        for (Element[] element : elements) {
            for (Element ele : element) {
                if(ele != null && ele.getType() == type){
                    count++;
                }
            }
        }
        return count;
    }

    /**
     * 元素下标转成坐标位置
     */
    public static Position coordinate(int index){
        int y = index / CatActivityConfig.COLUMN_NUM;
        int x = index - y * CatActivityConfig.COLUMN_NUM;
        return new Position(x, y);
    }

    /**
     * npcId 转 类型
     */
    public static int getElementAttrType(int id) {
        if(id >= 200 && id < 300){
            return eElementAttrTypes.Rivers.getType();
        }
        if(id >= 300 && id < 400){
            return eElementAttrTypes.Prison.getType();
        }
        if(id >= 400 && id < 500){
            return eElementAttrTypes.SpiceBox.getType();
        }
        if(id == 501){
            return eElementAttrTypes.Rail.getType();
        }
        if(id == 502){
            return eElementAttrTypes.Tram.getType();
        }
        return -1;
    }

    /**
     * 元素是否包含属性
     */
    public static EleAttr hasAttr(Element element, int type) {
        for (EleAttr attr : element.getAttrs()) {
            if(attr.getType() == type){
                return attr;
            }
        }
        return null;
    }

    /**
     * 复制状态
     */
    public static GameData copy(GameData data){
        GameData copy = new GameData();
        copy.setRoleBlood(data.getRoleBlood());
        copy.setRoleX(data.getRoleX());
        copy.setRoleY(data.getRoleY());
        copy.setAllRound(data.getAllRound());
        copy.setRound(data.getRound());
        copy.setDifficulty(data.getDifficulty());
        copy.setPass(data.getPass());
        copy.setBossBlood(data.getBossBlood());
        copy.setAngerBar(data.getAngerBar());
        copy.setDamage(data.getDamage());
        copy.setSettle(data.isSettle());
        copy.setStartTime(data.getStartTime());
        copy.setAllConnect(data.getAllConnect());
        copy.setSkillDamage(data.getSkillDamage());
        copy.setMonsterDamage(data.getMonsterDamage());
        copy.setKillSilent(data.isKillSilent());
        copy.setDharma(data.getDharma());
        copy.setBossId(data.getBossId());

        for (Map.Entry<Integer, Integer> entry : data.getRoleBloodLose().entrySet()) {
            copy.getRoleBloodLose().put(entry.getKey(), entry.getValue());
        }

        for (Map.Entry<Integer, Integer> entry : data.getMonsterSkill().entrySet()) {
            copy.getMonsterSkill().put(entry.getKey(), entry.getValue());
        }

        return copy;
    }

    /**
     * 位置不可重复
     */
    public static boolean isRepeat(List<Position> positionList){
        Set<Integer> indexSet = new HashSet<>();
        for (Position position : positionList) {
            int index = getIndex(position);
            if(indexSet.contains(index)){
                return true;
            }
            indexSet.add(index);
        }
        return false;
    }

    public static int getIndex(Position position) {
        return position.getY() * CatActivityConfig.COLUMN_NUM + position.getX();
    }

    public static boolean isTypeOrAttr(Element element, int type, int attr){
        return element.getType() == type || hasAttr(element, attr) != null;
    }

    public static void removeElementAttr(Element element, int attr){
        Iterator<EleAttr> iterator = element.getAttrs().iterator();
        while (iterator.hasNext()){
            EleAttr attr1 = iterator.next();
            if(attr1.getType() == attr){
                iterator.remove();
                break;
            }
        }
    }

    /**
     * 元素是否是阻碍状态
     */
    public static boolean isBlock(Element element){
        //未初始化(容错而已)
        if(element.getType() == eElementTypes.NotNull.getType()){
            return true;
        }
        //不变的障碍物
        if(element.getType() == eElementTypes.Null.getType()){
            return true;
        }
        //香料盒 闭合状态时，阻碍
        EleAttr attr = hasAttr(element, eElementAttrTypes.SpiceBox.getType());
        if(attr != null){
            return attr.getId() == 402;
        }
        //有轨道，没有电车
        if(CatMgr.hasAttr(element, eElementAttrTypes.Rail.getType()) != null && CatMgr.hasAttr(element, eElementAttrTypes.Tram.getType()) == null){
            return true;
        }
        return false;
    }

    public static void clearElementTypeInfo(Element element){
        element.setVal(0);
        element.setType(eElementTypes.NotNull.getType());
        element.setColor(0);
        element.setId(0);
    }

    public static void copyElementType(Element element, Element source){
        element.setType(source.getType());
        element.setVal(source.getVal());
        element.setColor(source.getColor());
        element.setId(source.getId());

        //element.getAttrs().clear();
        for (EleAttr attr : source.getAttrs()) {
            boolean add = false;
            for (EleAttr eleAttr : element.getAttrs()) {
                if(eleAttr.getType() == attr.getType()){
                    eleAttr.setVal(attr.getVal());
                    eleAttr.setColor(attr.getColor());
                    eleAttr.setId(attr.getId());
                    //CatMgr.getLogger().info("==============attr  copy type {},{}{}, source {}", eleAttr.getType(), element.getX(), element.getY(), JSONObject.toJSONString(source));
                    add = true;
                    break;
                }
            }
            if(!add) {
                element.getAttrs().add(attr);
                //CatMgr.getLogger().info("==============attr  add type {},{}{}, source {}", attr.getType(), element.getX(), element.getY(), JSONObject.toJSONString(source));
            }
        }
    }

    /**
     * 是否要生成达摩或者小怪
     */
    public static boolean needInit(Element element){
        //未初始化
        if(element.getType() == eElementTypes.NotNull.getType()){
            return true;
        }
        //监牢
        if(CatMgr.hasAttr(element, eElementAttrTypes.Prison.getType()) != null){
            return false;
        }
        //香盒
        if(CatMgr.hasAttr(element, eElementAttrTypes.SpiceBox.getType()) != null){
            return true;
        }
        //轨道+电车
        if(CatMgr.hasAttr(element, eElementAttrTypes.Rail.getType()) != null && CatMgr.hasAttr(element, eElementAttrTypes.Tram.getType()) != null){
            return true;
        }
        return false;
    }

    public static Element getElement(Element[][] elements, int x, int y){
        if(x < 0 || y < 0 || x >= CatActivityConfig.COLUMN_NUM || y >= CatActivityConfig.ROW_NUM){
            return null;
        }
        return elements[x][y];
    }

    public static Element getElementOrNull(Element[][] elements, int x, int y){
        if(!isValid(x, y)){
            return null;
        }
        return elements[x][y];
    }

    /**
     * 八个方向的元素
     */
    public static List<Element> getEightDirection(Element[][] elements, Position position) {
        List<Element> tempList = new ArrayList<>();
        //上、左上、左、左下；下、右下、右、右上
        int[][] offset = {{0, 1},{-1, 1},{-1, 0},{-1, -1},{0, -1},{1, -1},{1, 0},{1, 1}};
        for (int[] ints : offset) {
            Element element = getElementOrNull(elements,ints[0] + position.getX(), ints[1] + position.getY());
            if(element != null){
                tempList.add(element);
            }
        }
        return tempList;
    }

    /**
     * 四个方向的元素
     */
    public static List<Element> getFourDirection(Element[][] elements, Position position) {
        List<Element> tempList = new ArrayList<>();
        //上、左、下、右
        int[][] offset = {{0, 1},{-1, 0},{0, -1},{1, 0}};
        for (int[] ints : offset) {
            Element element = getElementOrNull(elements,ints[0] + position.getX(), ints[1] + position.getY());
            if(element != null){
                tempList.add(element);
            }
        }
        return tempList;
    }

    public static List<Element> getElementsByType(Element[][] elements, int type){
        List<Element> elementList = new ArrayList<>();
        for (Element[] element : elements) {
            for (Element ele : element) {
                if(ele.getType() == type){
                    elementList.add(ele);
                }
            }
        }
        return elementList;
    }

    public static List<Element> getElementsByType(Element[][] elements, int type, CatActivityConfig config, int skillType){
        List<Element> elementList = new ArrayList<>();
        for (Element element : getElementsByType(elements, type)) {
            CatNpcInfo catNpcInfo = config.getCatNpcInfoById(element.getId());
            if(catNpcInfo != null && catNpcInfo.getSkillType() == skillType){
                elementList.add(element);
            }
        }
        return elementList;
    }

    /**
     * 随机不重复的小怪
     * @param filterSilent 是否不生产沉默小怪
     */
    public static List<Element> randomMonsterElement(CatActivityConfig config, CatMissionInfo missionInfo, boolean filterSilent){
        if(StringUtils.isNullOrEmpty(missionInfo.getMonsterId())){
            return new ArrayList<>();
        }
        int monsterNum = Integer.parseInt(missionInfo.getMonsterNumber());
        if(monsterNum <= 0){
            return new ArrayList<>();
        }

        List<Element> result = new ArrayList<>();
        //最大循环次数
        int loop = 10000;
        List<Integer> keyList = new ArrayList<>();
        List<Integer> weightList = new ArrayList<>();
        List<Integer> bloodList = new ArrayList<>();

        List<String> itemConfigList = StringUtils.stringToStringList(missionInfo.getMonsterId(), "\\|");
        for (String itemConfigStr : itemConfigList) {
            List<Integer> list = StringUtils.stringToIntegerList(itemConfigStr, ";");
            keyList.add(list.get(0));
            weightList.add(list.get(1));
            bloodList.add(list.get(2));
        }

        List<Integer> tempKeyList = new ArrayList<>(keyList);
        List<Integer> tempWeightList = new ArrayList<>(weightList);
        List<Integer> tempBloodList = new ArrayList<>(bloodList);

        Random random = new Random();
        while (loop > 0 && monsterNum > 0){
            int index = RandomHelper.getRandomIndexByWeight(tempWeightList, random);
            Element element = new Element();
            int id = tempKeyList.remove(index);
            tempWeightList.remove(index);
            CatNpcInfo npcInfo = config.getCatNpcInfoById(id);
            if(filterSilent && npcInfo.getSkillType() == 5){
                if(tempKeyList.size() == 0){
                    tempKeyList = new ArrayList<>(keyList);
                    tempWeightList = new ArrayList<>(weightList);
                    tempBloodList = new ArrayList<>(bloodList);
                }
                continue;
            }
            element.setId(id);
            element.setVal(tempBloodList.remove(index));
            element.setType(eElementTypes.Monster.getType());
            result.add(element);
            loop--;
            monsterNum--;

            if(tempKeyList.size() == 0){
                tempKeyList = new ArrayList<>(keyList);
                tempWeightList = new ArrayList<>(weightList);
                tempBloodList = new ArrayList<>(bloodList);
            }
        }
        return result;
    }

    public static List<Integer> getRandomPositionByWeight(CatActivityConfig config){
        if(config == null || config.getMagnumWeights().size() == 0){
            return getRandomElementIndex();
        }
        List<Integer> weightList = new ArrayList<>(config.getMagnumWeights());
        Random random = new Random();
        List<Integer> valueList = new ArrayList<>(4);
        valueList.add(1);
        valueList.add(2);
        valueList.add(3);
        valueList.add(4);
        List<Integer> result = new ArrayList<>();
        while (weightList.size() > 0) {
            int idx = RandomHelper.getRandomIndexByWeight(weightList, random);
            weightList.remove(idx);
            result.add(valueList.remove(idx));
        }
        List<Integer> randomList = new ArrayList<>();
        int[] huanOne = new int[]{24};
        int[] huanTwo = new int[]{16, 17, 18, 23, 25, 30, 31, 32};
        int[] huanThree = new int[]{8, 9, 10, 11, 12, 15, 19, 22, 26, 29, 33, 36, 37, 38, 39, 40};
        int[] huanFour = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 13, 14,20, 21, 27,28, 34, 35, 41, 42, 43, 44, 45, 46, 47, 48};
        for (int i : result) {
            if(i == 1){
                randomList.add(huanOne[0]);
            }else if(i == 2){
               List<Integer> indexList = RandomHelper.getDifferentRandomNum(huanTwo.length, huanTwo.length);
               for (int k : indexList) {
                   randomList.add(huanTwo[k]);
               }
            }else if(i == 3){
                List<Integer> indexList = RandomHelper.getDifferentRandomNum(huanThree.length, huanThree.length);
                for (int k : indexList) {
                    randomList.add(huanThree[k]);
                }
            }else if(i == 4){
                List<Integer> indexList = RandomHelper.getDifferentRandomNum(huanFour.length, huanFour.length);
                for (int k : indexList) {
                    randomList.add(huanFour[k]);
                }
            }
        }
        //CatMgr.getLogger().info("-------- randomList : {}", StringUtils.listToString(randomList, ","));
        return randomList;
    }

    public static void initMonsterElement(CatActivityConfig config, Random random, Element element, Element temp) {
        element.setType(temp.getType());
        element.setVal(temp.getVal());
        element.setId(temp.getId());

        int idx = RandomHelper.getRandomIndexByWeight(config.getBuffWeightList(), random);
        List<Integer> buffVal = StringUtils.stringToIntegerList(config.getBuffList().get(idx), ";");
        element.setColor(idx);
        element.setVal(element.getVal() + buffVal.get(0));

        //小怪有存活属性
        EleAttr attr = new EleAttr(eElementAttrTypes.Survive.getType(), 0);
        element.getAttrs().add(attr);

        //CatMgr.getLogger().info("初始小怪：{}", JSONObject.toJSONString(element));
    }
}
